import cryptoJs from 'crypto-js'
const MarkdownIt = require('markdown-it')
const hljs = require('highlight.js')
const toc = require('markdown-it-toc')

/**
 * 生成随机字符串
 * @returns { String }
 */
export const newRandomId = () => {
  let randomId = ''
  for (let i = 1; i <= 8; i++) {
    const n = Math.floor(Math.random() * 16.0).toString(16)
    randomId += n
  }
  let total = 0
  for (let i = 0; i < randomId.length; i++) {
    total += isNaN(parseInt(randomId[i])) ? 6 : parseInt(randomId[i])
  }
  return randomId + String(total % 9)
}

/**
 * 生成随机字符串
 * @returns { String }
 */
export const new15RandomId = () => {
  let randomId = ''
  for (let i = 1; i <= 15; i++) {
    const n = Math.floor(Math.random() * 16.0).toString(16)
    randomId += n
  }
  let total = 0
  for (let i = 0; i < randomId.length; i++) {
    total += isNaN(parseInt(randomId[i])) ? 6 : parseInt(randomId[i])
  }
  return randomId + String(total % 9)
}

//  判断是否为空
export function isBlank (value) {
  return (
    value === undefined ||
    value === null ||
    false ||
    value === '' ||
    value.toString().trim() === '' ||
    value.toString().toLocaleLowerCase().trim() === 'null'
  )
}

/**
 * 加密
 * @param { String } data 需要加密的数据
 * @param { String } key 公钥key
 * @param { String } iv
 */
export const encrypt = (data, key, iv) => {
  const okey = cryptoJs.enc.Utf8.parse(key)
  const oiv = cryptoJs.enc.Utf8.parse(iv)
  const srcs = cryptoJs.enc.Utf8.parse(data)
  const encrypted = cryptoJs.AES.encrypt(srcs, okey, {
    iv: oiv,
    mode: cryptoJs.mode.CBC,
    padding: cryptoJs.pad.ZeroPadding
  })
  return encrypted.toString()
}

/**
 * 防抖函数
 * @param { Function } fn 需要执行的函数
 * @param { Number } delay 延迟执行时间
 * @returns { Function }
 */
export const debounce = (fn, delay = 500) => {
  let timer = null
  const that = this
  return function (...args) {
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      timer = null
      fn.apply(that, args)
    }, delay)
  }
}

/**
 * 校验所有信息唯一keyid格式
 * @param { String } unipId
 */
export const validateUniqId = (uniqId) => {
  if (uniqId.length !== 16) {
    return false
  }
  let total = 0
  for (let i = 0; i < uniqId.length - 1; i++) {
    total += isNaN(parseInt(uniqId[i])) ? 6 : parseInt(uniqId[i])
  }
  if (String(total % 9) !== uniqId[uniqId.length - 1]) {
    return false
  }
  return true
}

/**
 * calculate time
 * @parma { String } date
 */
export const cycleDate = (date) => {
  const dateTimeStamp = new Date(date).getTime()
  const minute = 1000 * 60
  const hour = minute * 60
  const day = hour * 24
  const month = day * 30
  const year = month * 12
  const now = new Date().getTime()
  const diffValue = now - dateTimeStamp
  const yearC = diffValue / year
  const monthC = diffValue / month
  const weekC = diffValue / (7 * day)
  const dayC = diffValue / day
  const hourC = diffValue / hour
  const minC = diffValue / minute
  if (yearC >= 1) {
    return parseInt(yearC) + '年前'
  } else if (monthC >= 1) {
    return parseInt(monthC) + '个月前'
  } else if (weekC >= 1) {
    return parseInt(weekC) + '周前'
  } else if (dayC >= 1) {
    return parseInt(dayC) + '天前'
  } else if (hourC >= 1) {
    return parseInt(hourC) + '小时前'
  } else if (minC >= 1) {
    return parseInt(minC) + '分钟前'
  }
  return '刚刚'
}

export const cycleImDate = (date, simple = false) => {
  if (!date) return ''
  const dateNow = new Date()
  const year = date.substr(0, 4)
  const month = date.substr(5, 2)
  const day = date.substr(8, 2)
  const hour = date.substr(11, 2)
  const minute = date.substr(14, 2)
  const currentY = dateNow.getFullYear()
  const currentM = dateNow.getMonth() + 1
  const currentD = dateNow.getDate()
  if (year * 1 !== currentY) {
    return simple ? `${year}/${month}/${day}` : `${year}年${month}月${day}日 ${hour}:${minute}`
  } else if (month * 1 !== currentM) {
    return simple ? `${month}/${day}` : `${month}月${day}日 ${hour}:${minute}`
  } else if (currentD - day < 1) {
    return `${hour}:${minute}`
  } else if (currentD - day < 2) {
    return simple ? '昨天' : `昨天 ${hour}:${minute}`
  } else if (currentD - day < 3) {
    return simple ? '前天' : `前天 ${hour}:${minute}`
  }
  return simple ? `${month}/${day}` : `${month}月${day}日 ${hour}:${minute}`
}

/**
 * get base64
 * @param {*} file
 * @returns
 */
export const getBase64 = (file) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = () => resolve(reader.result)
    reader.onerror = (error) => reject(error)
  })
}

export const getImageSize = file => {
  return new Promise(resolve => {
    const reader = new FileReader()
    reader.onloadend = function () {
      const img = new Image()
      img.onload = function () {
        resolve({ width: img.width, height: img.height })
      }
      img.src = reader.result
    }
    reader.readAsDataURL(file)
  })
}

export const getMarkdownTos = (ele) => {
  const navigatorList = ele?.querySelectorAll('a')
  const tocs = []
  if (!navigatorList) return tocs
  const minHead = Math.min(...Array.from(navigatorList)
    .map(o => Number(o.parentNode.nodeName.substr(1, 1)))
    .filter(Boolean))
  Array.from(navigatorList).filter(item => item.id).forEach((item, index) => {
    const id = `markdown-heading-${index}`
    const parentNode = item.parentNode
    parentNode.setAttribute('id', id)
    const parentNodeName = parentNode.nodeName
    if (item.id) {
      tocs.push({
        href: id,
        name: parentNode.innerText,
        depth: Number(parentNodeName.substr(1, 1)) - minHead
      })
    }
  })
  return tocs
}

export const removeScriptAndLink = () => {
  const links = document.querySelectorAll("link[href^='/md/']")
  const scripts = document.querySelectorAll("script[src^='/md/']")
  Array.from(links).concat(Array.from(scripts)).forEach(el => {
    el.remove()
  })
}

export const resetLocationSearchURL = (objects) => {
  let newUrl = window.location.pathname
  if (objects) {
    const searchParams = new URLSearchParams(window.location.search)
    for (const key in objects) {
      searchParams.set(key, objects[key])
    }
    newUrl = `${window.location.pathname}?${searchParams.toString()}`
  }
  window.history.pushState({ path: newUrl }, '', newUrl)
}

export const getElementDistanceFromTop = (element) => {
  let distance = 0
  while (element) {
    distance += element.offsetTop
    element = element.offsetParent
  }
  return distance
}

/**
 * 向上寻找指定类名的父节点
 * @param {*} element
 * @param {*} className
 * @returns
 */
export const getTargetParentNode = (element, className) => {
  while (element && element.tagName !== 'BODY') {
    if (element.className.includes(className)) {
      return element
    }
    element = element.parentNode
  }
  return false
}

/**
 * 时间格式化
 * @param {*} date
 * @param {*} fmt
 * @returns
 */
export const dateFormat = (date, fmt = 'YYYY-mm-dd HH:MM:SS') => {
  let ret
  const opt = {
    'Y+': date.getFullYear().toString(),
    'm+': (date.getMonth() + 1).toString(),
    'd+': date.getDate().toString(),
    'H+': date.getHours().toString(),
    'M+': date.getMinutes().toString(),
    'S+': date.getSeconds().toString()
  }
  for (const k in opt) {
    ret = new RegExp('(' + k + ')').exec(fmt)
    if (ret) {
      fmt = fmt.replace(ret[1], (ret[1].length === 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, '0')))
    }
  }
  return fmt
}

export const getTimePeriod = () => {
  var currentTime = new Date()
  var currentHour = currentTime.getHours()

  if (currentHour >= 5 && currentHour < 9) {
    return '早上'
  } else if (currentHour >= 9 && currentHour < 12) {
    return '上午'
  } else if (currentHour >= 12 && currentHour < 14) {
    return '中午'
  } else if (currentHour >= 14 && currentHour < 18) {
    return '下午'
  } else {
    return '晚上'
  }
}

export const calcLevelFromExp = (exp) => {
  let k = 1
  let level = 1
  while (k * 50 < exp) {
    level += 1
    k += level
  }
  return Math.min(level, 7)
}

/**
 * 从md文件中找出所有域名不为https://image.zdxblog.cn的图片
 * @param {*} md
 */
export function getImageLinksFromMD (md) {
  const links = []
  const imageRegex = /!\[.*?\]\(([^)]+)\)/g // 匹配 ![]() 格式的图片链接
  // 获取所有图片链接
  let match
  while ((match = imageRegex.exec(md)) !== null) {
    const imageLink = match[1]
    if (!imageLink.includes('https://image.zdxblog.cn')) {
      links.push(imageLink)
    }
  }
  return links
}

export function getURLSearchParams (url) {
  const paramsRegex = /[?&]([^=]+)=([^&]*)/g
  const params = {}
  let match

  while ((match = paramsRegex.exec(url)) !== null) {
    const paramName = decodeURIComponent(match[1])
    const paramValue = decodeURIComponent(match[2])
    params[paramName] = paramValue
  }

  return params
}

export function loadWhithoutSearchURL () {
  const parsedUrl = new URL(location.href)
  parsedUrl.search = ''
  window.history.pushState({}, document.title, parsedUrl.toString())
}

export const md = new MarkdownIt({
  html: true,
  xhtmlOut: true,
  breaks: true,
  linkify: true,
  typographer: true,
  quotes: '“”‘’',
  langPrefix: 'lang--',
  highlight: function (str, lang) {
    if (hljs.getLanguage(lang || 'javascript')) {
      try {
        return `<pre><div class="hljs"><code class="lang-${lang || 'javascript'}">${hljs.highlight(lang || 'javascript', str, true).value}</code></div></pre>`
      } catch (__) {}
    }

    return `<pre><div class="hljs><code>${md.utils.escapeHtml(str)}</code></div></pre>`
  }
}).use(toc)
